import $store from "@/store";
import {
  jbConfig,
  appPlatform,
  localStorageKey,
  baseURL,
  devMode
} from "@/config/index";
import { toast } from "../utils/index";
// 是否显示日志打印
const openLog = devMode;
// 是否可配置显示loading
const openLoadingAlways = false;

// 请求方式
export const METHOD = {
  POST: "POST",
  GET: "GET"
};
const errorMessage = {
  success: "成功",
  fail: "失败",
  unlogin: "登录异常",
  error: "发生异常",
  neterror: "网络异常",
  loading: "加载中...",
  loadfail: "加载失败"
};

//code 和后台接口对应
export const errorCode = {
  "4000": "系统异常",
  "4004": "尚未登录",
  "4005": "JWT过期处理",
  "4030": "refreshjwt过期",
  "4080": "新用户需要注册"
};

const _fetchBase = (myConfig, times = 0) => {
  return new Promise((resolve, reject) => {
    let params = {};
    if (myConfig.params) {
      for (let key in myConfig.params) {
        if (
          myConfig.params[key] !== null &&
          myConfig.params[key] !== undefined
        ) {
          params[key] = myConfig.params[key];
        }
      }
    }
    if (myConfig.loading) {
      uni.showLoading({
        title: "加载中",
        mask: true
      });
    }

    let customHeader = { platform: appPlatform };
    //添加后端api需要的请求头
    if (jbConfig.ENABLE) {
      customHeader[jbConfig.JBOLT_API_REQUEST] = "true";
      customHeader[jbConfig.JBOLT_APPID_KEY] = jbConfig.APPID;
    }

    let token = uni.getStorageSync(localStorageKey.token);
    let refreshToken = uni.getStorageSync(localStorageKey.refreshToken);
    if (myConfig.auth) {
      if (jbConfig.ENABLE) {
        if (myConfig.withRefreshJwt) {
          customHeader[jbConfig.JBOLT_REFRESH_JWT_KEY] = refreshToken;
        } else {
          customHeader[jbConfig.JBOLT_JWT_KEY] = token;
        }
        if (jbConfig.JBOLT_JWT_CHECKSIGN) {
          let jbsign = createSignature(false);
          customHeader[jbConfig.JBOLT_JWT_SIGNATURE_KEY] = jbsign.signature;
          customHeader[jbConfig.JBOLT_JWT_TIMESTAMP_KEY] = jbsign.timestamp;
          customHeader[jbConfig.JBOLT_JWT_NONCE_KEY] = jbsign.nonce;
        }
      } else {
        customHeader["token"] = token;
      }
    }
    uni.request({
      url: myConfig.apiBaseUrl + myConfig.api,
      method: myConfig.method || METHOD.POST,
      data: params,
      header: Object.assign(
        customHeader,
        {
          "content-type": "application/x-www-form-urlencoded;charset=utf-8",
          "X-Requested-With": "XMLHttpRequest"
        },
        myConfig.header
      ),
      success: async res => {
        let resHeader = res.header;
        let resData = res.data;
        if (myConfig.loading) {
          uni.hideLoading();
        }
        if (openLog) {
          console.log(
            `---------------api 请求参数--------------\n` +
              `请求地址: ${myConfig.api}\n` +
              `请求参数:\n` +
              `${JSON.stringify(myConfig.params)}\n` +
              `------------------------------------------------------`
          );
          console.log("返回结果", resData);
          console.log("------------------------------------------------------");
        }
        if (resData && resData.state == "ok") {
          //不处理预检信息
          if (resData.data && resData.data["OPTIONS"] == 1) {
            console.log("======OPTIONS SUCCESS======");
            return false;
          }
          //如果有jwt返回
          let jwt = resHeader["jboltjwt"];
          let refreshToken = resHeader["jboltrefreshjwt"];
          if (jwt) {
            resData.data = Object.assign(
              {
                token: jwt,
                refreshToken: refreshToken
              },
              resData.data?resData.data:{}
            );
          }
          resolve(resData.data);
          return true;
        } else if (
          resData.state == "fail" &&
          myConfig.auth &&
          (resData.code === 4030 ||
            resData.code === 4005 ||
            resData.code === 4004)
        ) {
          $store.dispatch("removeToken");
          $store.dispatch("removeUserInfo");
          $store.dispatch("removeSessionKey");
          if (resData.code === 4030) {
            //refreshjwt也过期了
            $store.dispatch("removeRefreshToken");
          }

          if (myConfig.login) {
            if (times === 0) {
              let refreshRes = await $store.dispatch("refreshJwtToken");
              if (refreshRes) {
                return _fetchBase(myConfig, times + 1);
              }
            }
            toast(errorMessage.unlogin);
            setTimeout(() => {
              uni.switchTab({
                url: "/pages/index/index"
              });
            }, 1000);
          }
          return false;
        } else {
          if (!myConfig.error) {
            if (resData.msg) {
              reject(resData);
              toast(resData.msg);
            } else {
              toast(errorMessage.fail);
            }
          } else {
            reject(resData);
          }
          return false;
        }
      },
      fail(err) {
        if (myConfig.loading) {
          uni.hideLoading();
        }
        if (!myConfig.error) {
          // #ifndef H5
          toast(errorMessage.neterror);
          // #endif
        } else {
          reject(err);
        }
      }
    });
  });
};

export const fetch = myConfig => {
  const defaultConfig = {
    apiBaseUrl: baseURL,
    api: "",
    method: METHOD.POST,
    params: null,
    error: false,
    loading: true,
    auth: true,
    login: true,
    withRefreshJwt: false,
    header: {}
  };
  myConfig = Object.assign({}, defaultConfig, myConfig);
  if (openLoadingAlways) myConfig.loading = true;

  myConfig.params = myConfig.params || {};
  return new Promise(async (resolve, reject) => {
    _fetchBase(myConfig).then(
      fetchRes => {
        resolve(fetchRes);
      },
      err => {
        reject(err);
      }
    );
  });
};
